from django.db.models import QuerySet
from django.db.models.manager import BaseManager
from .deletion import BaseModelCollector


class BaseModelQuerySet(QuerySet):
    """重写 QuerySet 的 delete() """

    def delete(self):
        """逻辑删除"""

        self._not_support_combined_queries('delete')
        assert not self.query.is_sliced, \
            "Cannot use 'limit' or 'offset' with delete."

        if self.query.distinct or self.query.distinct_fields:
            raise TypeError('Cannot call delete() after .distinct().')
        if self._fields is not None:
            raise TypeError("Cannot call delete() after .values() or .values_list()")

        del_cond = self.model.OwnMeta.del_cond
        queryset = self.filter(**del_cond)

        # 删除实际上是2个查询 一个是查找相关联对象 另一个是删除
        # 确保在相同数据库上执行相关联对象的删除
        queryset._for_write = True

        # 禁用不支持的字段
        queryset.query.select_for_update = False
        queryset.query.select_related = False
        queryset.query.clear_ordering(force_empty=True)

        # 汇集要删除的对象
        collector = BaseModelCollector(using=queryset.db)
        collector.collect(queryset)
        deleted, _rows_count = collector.delete()

        # 清除结果缓存 以防此 QuerySet 被重用
        self._result_cache = None
        return deleted, _rows_count

    def destroy(self):
        """物理删除"""
        return super().delete()


class BaseModelManager(BaseManager.from_queryset(BaseModelQuerySet)):
    """查询管理器"""

    def all(self, contain_deleted=False):
        """默认返回所有未删除的数据"""

        if contain_deleted:
            return super().all()
        del_cond = self.model.OwnMeta.del_cond
        return self.filter(**del_cond)
